/*
 * Copyright 2022 ByteDance Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

namespace sonic_json {
namespace internal {

// kEscapedMap maps the escaped char into origin char, as follows:
// ['/' ] = '/',
// ['"' ] = '"',
// ['b' ] = '\b',
// ['f' ] = '\f',
// ['n' ] = '\n',
// ['r' ] = '\r',
// ['t' ] = '\t',
// ['u' ] = -1,
// ['\\'] = '\\',
static const uint8_t kEscapedMap[256] = {
    0, 0, 0,    0, 0,    0, 0,    0, 0, 0, 0, 0, 0,    0, 0,    0,
    0, 0, 0,    0, 0,    0, 0,    0, 0, 0, 0, 0, 0,    0, 0,    0,
    0, 0, '"',  0, 0,    0, 0,    0, 0, 0, 0, 0, 0,    0, 0,    '/',
    0, 0, 0,    0, 0,    0, 0,    0, 0, 0, 0, 0, 0,    0, 0,    0,

    0, 0, 0,    0, 0,    0, 0,    0, 0, 0, 0, 0, 0,    0, 0,    0,
    0, 0, 0,    0, 0,    0, 0,    0, 0, 0, 0, 0, '\\', 0, 0,    0,
    0, 0, '\b', 0, 0,    0, '\f', 0, 0, 0, 0, 0, 0,    0, '\n', 0,
    0, 0, '\r', 0, '\t', 0, 0,    0, 0, 0, 0, 0, 0,    0, 0,    0,

    0, 0, 0,    0, 0,    0, 0,    0, 0, 0, 0, 0, 0,    0, 0,    0,
    0, 0, 0,    0, 0,    0, 0,    0, 0, 0, 0, 0, 0,    0, 0,    0,
    0, 0, 0,    0, 0,    0, 0,    0, 0, 0, 0, 0, 0,    0, 0,    0,
    0, 0, 0,    0, 0,    0, 0,    0, 0, 0, 0, 0, 0,    0, 0,    0,

    0, 0, 0,    0, 0,    0, 0,    0, 0, 0, 0, 0, 0,    0, 0,    0,
    0, 0, 0,    0, 0,    0, 0,    0, 0, 0, 0, 0, 0,    0, 0,    0,
    0, 0, 0,    0, 0,    0, 0,    0, 0, 0, 0, 0, 0,    0, 0,    0,
    0, 0, 0,    0, 0,    0, 0,    0, 0, 0, 0, 0, 0,    0, 0,    0,
};

// GCC didn't support non-trivial designated initializers C99 extension
struct QuotedChar {
  long n;
  const char *s;
};

static const struct QuotedChar kQuoteTab[256] = {
    // 0x00 ~ 0x1f
    {.n = 6, .s = "\\u0000\0\0"},
    {.n = 6, .s = "\\u0001\0\0"},
    {.n = 6, .s = "\\u0002\0\0"},
    {.n = 6, .s = "\\u0003\0\0"},
    {.n = 6, .s = "\\u0004\0\0"},
    {.n = 6, .s = "\\u0005\0\0"},
    {.n = 6, .s = "\\u0006\0\0"},
    {.n = 6, .s = "\\u0007\0\0"},
    {.n = 2, .s = "\\b\0\0\0\0\0\0"},
    {.n = 2, .s = "\\t\0\0\0\0\0\0"},
    {.n = 2, .s = "\\n\0\0\0\0\0\0"},
    {.n = 6, .s = "\\u000b\0\0"},
    {.n = 2, .s = "\\f\0\0\0\0\0\0"},
    {.n = 2, .s = "\\r\0\0\0\0\0\0"},
    {.n = 6, .s = "\\u000e\0\0"},
    {.n = 6, .s = "\\u000f\0\0"},
    {.n = 6, .s = "\\u0010\0\0"},
    {.n = 6, .s = "\\u0011\0\0"},
    {.n = 6, .s = "\\u0012\0\0"},
    {.n = 6, .s = "\\u0013\0\0"},
    {.n = 6, .s = "\\u0014\0\0"},
    {.n = 6, .s = "\\u0015\0\0"},
    {.n = 6, .s = "\\u0016\0\0"},
    {.n = 6, .s = "\\u0017\0\0"},
    {.n = 6, .s = "\\u0018\0\0"},
    {.n = 6, .s = "\\u0019\0\0"},
    {.n = 6, .s = "\\u001a\0\0"},
    {.n = 6, .s = "\\u001b\0\0"},
    {.n = 6, .s = "\\u001c\0\0"},
    {.n = 6, .s = "\\u001d\0\0"},
    {.n = 6, .s = "\\u001e\0\0"},
    {.n = 6, .s = "\\u001f\0\0"},
    // 0x20 ~ 0x2f
    {0, 0},
    {0, 0},
    {.n = 2, .s = "\\\"\0\0\0\0\0\0"},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    // 0x30 ~ 0x4f
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    // 0x50 ~ 0x5f
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {.n = 2, .s = "\\\\\0\0\0\0\0\0"},
    {0, 0},
    {0, 0},
    {0, 0},
    // 0x60 ~ 0xff
};

static const bool kNeedEscaped[256] = {
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};

}  // namespace internal
}  // namespace sonic_json
